#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <syslog.h>
#include <time.h>
#include <assert.h>
#include <semaphore.h>

#include "ctrl.h"
#include "zlog.h"
#include "iniparser.h"
#include "cjson/cJSON.h"
#include "sqlite3.h"
#include "security_manage.h"
#include "BussinessTerminalManage.h"
#include "upload.h"
#include "shell.h"
#include "microApp.h"
#include "container.h"
#include "dictionary_ctrl.h"
#include "ota.h"
#include "map.h"
#include "define.h"

ob_context g_mqtt_ob;
sqlite3 *g_sqlite3_db;
ST_MODEL_CTL g_st_model_ctl;
ob_context g_gb_ob;
map_void_t g_SubDeviceID;				//开关子设备跟CPUID间的映射表
map_void_t g_CcoStaDeviceID;			//CCO、STA子设备认证结果映射表

int MQTT_PROTOCOL = 1;
int TCP_PROTOCOL = 1;

char *VERSION_NO;
int GB_TARGET = 0;

char *FILE_SERVER_IP;
int FILE_SERVER_PORT = 0;
char *FILE_LOG;
char *DB_FILENAME;
char *DOCKER_URL;
char *DOCKER_SOCK;
char *DOCKER_PATH;
char *UPDATE_FILE_PATH;
char *APP_FILE_PATH;
char *LOGIN_ADDR;
char *LOGIN_USER;
char *LOGIN_PASSWORD;
char *LOGIN_ZONE;
char *LOGIN_NODE;
int LOGIN_PORT = 0;
int ACTIVATION_PORT = 0;
int PRIORITY_CONF = 0;
// 认证文件路径
char *AUTH_PATH;
int HTTP_SSL = 0;
int Activation_SSL = 2;
int IS_HTTPS = 0;
int file_sencrypt = 0;
char *CLIENT_SIGN_CERT_PATH;
char *CLIENT_SIGN_KEY_PATH;
char *CLIENT_ENC_CERT_PATH;
char *CLIENT_ENC_KEY_PATH;
char *CLIENT_CA_CERT_PATH;

char* CLIENT_CA_CERT_PATH_V1;
char* CLIENT_SIGN_CERT_PATH_V1;
char* CLIENT_SIGN_KEY_PATH_V1;

char SmartProbe_ini[128] = "./conf/EagleEyeSMG.ini"; // 这个文件放可配置的，不加密
char mqtt_ini[128] = "./conf/mqtt.ini";
char rule_ini[128] = "./conf/rule.ini";

// 数盾
char *SD_ADDR_PORT = NULL;
char *SD_TEM_CERT_ADDR_PORT = NULL;
char *SD_CERT_ADDR_PORT = NULL;
char *WEB_ADDR_PATH = NULL;
char *WEB_ADDR_PORT = NULL;
char *SD_FRONT_PORT = NULL;

sem_t m_getCert;
extern pthread_mutex_t g_clientMutex;

// 定义表结构 
#define CREATE_NETWORK_TRAFFIC_TABLE_SQL \
    "CREATE TABLE IF NOT EXISTS network_traffic (" \
    "port_name TEXT NOT NULL, " \
    "date_ym TEXT NOT NULL, " \
    "rx_total UNSIGNED BIG INT DEFAULT 0 CHECK (rx_total >= 0), " \
    "tx_total UNSIGNED BIG INT DEFAULT 0 CHECK (tx_total >= 0), " \
    "tx_prev UNSIGNED BIG INT DEFAULT 0 CHECK (tx_prev >= 0), " \
    "rx_prev UNSIGNED BIG INT DEFAULT 0 CHECK (rx_prev >= 0), " \
    "PRIMARY KEY (port_name, date_ym));"


// 可供外部组件调用接口
void handleExternalInterface1(void *context, void *param)
{
	printf("handleExternalInterface1() ......\n");
}

void external_proc()
{
	setExternalCallbacks();
}

void internal_proc()
{
	setInternalCallbacks();
}

void ctrl_proc()
{
	// 异常捕捉机制
	setExceptCallbacks();
	srand(time(NULL));  // 仅调用一次,为了生成随机数
	// 对象初始化
	if (MQTT_PROTOCOL)
	{
		g_mqtt_ob.status = 1;
		g_mqtt_ob.cmdPq = cQcreate(CQUEUE_MAX);
		g_mqtt_ob.netPq = cQcreate(CQUEUE_MAX);
		g_mqtt_ob.setLoginConfig = setLoginConfig;
		// g_mqtt_ob.setCallbacks = setMqttCallbacks;
		g_mqtt_ob.Login = IOTA_Login;
		g_mqtt_ob.pthread_manage = pthread_manage;
		g_mqtt_ob.setCallbacks = setCallbacks;

		/// 终端业务
		if (g_st_model_ctl.deviceFlag) // Terminal Manage Bussiness
		{
			g_pFunTerminalSyncTime = terminalSyncTime;
			g_pFunTerminalReboot = terminalReboot;
			g_pFunTerminalManage = terminalManageBaseInfo;
			g_pFunTerminalLog = terminalLog;
			g_pFunTerminalLogLevel = terminalLogLevel;
			g_pFunsetFullReport = terminalprocessCmd;
			g_pFundataSpaceService = terminaldataSpaceService;
			g_pFunUsbPlugging = terminalUsbPlugging;
			g_pFunStartDepend = terminalStartDepend;
			g_pFunUpdateCer = terminalUpdateCer;
			g_pFunSubDeviceAuth = terminalSubDeviceAuth;
			g_pFunQueryScram = terminalQueryMqttScram;

			g_pFunTerminalPublish = terminalRuntimeData;
			g_pFunTerminalSetConfig = terminalSetDataReportConfig;
			g_pFunTerminalUpdate = terminalServiceUpdate;
			g_pFunFirmwareDownload = firmwareServiceDownload;
			g_pFunFirmwareUpgrade = firmwareServiceUpgrade;
			g_pFunactionPatchDownload = actionPatchDownload;
			g_pFunactionConfigDownalod = actionConfigDownalod;
			g_pFunactionConfigUpgrade = actionPatchUpgrade;
			// 链路追踪
			g_pFunTerminalCallLinkTrace = terminalcallLinkTrace;
			// 下发配置
			g_pFunConfManage = terminalManageConf;
			g_pFunTerminal_Init = eagleEyeInit;
			g_pFunrealTimeMonitoring = realTimeMonitoring;

			g_pFunlowPowerSleepConf = lowPowerSleepConf;
		}

		
		if (g_st_model_ctl.securityFlag)
		{
			g_pFunSecurityProc = security_proc; 		// 告警业务
			g_pFunSecurityCommond = security_commond;   // 安全业务
		} 

		// 微服务业务
		if (g_st_model_ctl.appFlag)
		{
			g_pFunTerminalAppCommond = app_commond;
		}

		// 容器业务
		if (g_st_model_ctl.virtualizationFlag)
		{
			g_pFunTerminalConCommond = container_command;
		}
		// 文件信息获取
		g_pFunTerminalDirCommond = dictionary_commond;

		// 安全业务  
		if (g_st_model_ctl.safeFlag)
		{

		}

		// 第三方 使能后面加
		if (g_st_model_ctl.third)
		{
			g_pFunThirdModule = ThirdModuleMain;
		}
		// 载波网管后面加
		if (g_st_model_ctl.plc)
		{
			g_pFunPlcModule = PlcModuleMain;
		}

		// 网络延时测试
		g_pFunnetDelayTest = netDelayTest;

		// ota升级
		g_pFunTerminalOTACommond = ota_commond;

		// 设置网络接收回调
		IOTA_SetCallBackSurAg(proMsg);
	}
}

int sqlite3_init()
{
	int rc = sqlite3_open(DB_FILENAME, &g_sqlite3_db);
	const char *sqlversion = sqlite3_libversion();
	dzlog_info("SQLite 版本: %s\n", sqlversion);
	if (rc)
	{
		dzlog_error("sqlite3_open error: %s", sqlite3_errmsg(g_sqlite3_db));
		return -1;
	}
	else
	{
		dzlog_info("sqlite3_open succ");
		if (sqlite3_exec(g_sqlite3_db, "PRAGMA foreign_keys = ON;",
			NULL, NULL, NULL) != SQLITE_OK) {
			dzlog_info("外键约束启用失败");
		}
		// 检查表是否存在 
		char* errmsg = NULL;
		int table_exists = 0;
		const char* check_sql =
			"SELECT 1 FROM sqlite_master "
			"WHERE type='table' AND name='network_traffic';";

		// 使用预处理语句避免SQL注入 
		sqlite3_stmt* stmt;
		rc = sqlite3_prepare_v2(g_sqlite3_db, check_sql, -1, &stmt, NULL);
		if (rc == SQLITE_OK) {
			if (sqlite3_step(stmt) == SQLITE_ROW) {
				table_exists = 1;
			}
			sqlite3_finalize(stmt);
		}
		else {
			dzlog_error("表检查失败: %s", sqlite3_errmsg(g_sqlite3_db));
			sqlite3_close(g_sqlite3_db);
			return -1;
		}

		// 创建表（如果不存在）
		if (!table_exists) {
			dzlog_info("正在创建 network_traffic 表");
			rc = sqlite3_exec(g_sqlite3_db, CREATE_NETWORK_TRAFFIC_TABLE_SQL,
				NULL, NULL, &errmsg);
			if (rc != SQLITE_OK) {
				dzlog_error("建表失败: %s", errmsg);
				sqlite3_free(errmsg);
				sqlite3_close(g_sqlite3_db);
				return -1;
			}
			dzlog_info("表创建成功");
		}
		else {
			//dzlog_info("表已存在，跳过创建");
		}


		char* err_msg = NULL;

		// SQL语句：如果表不存在则创建
		const char* create_table_sql =
			"CREATE TABLE IF NOT EXISTS network_firewall ("
			"policyId TEXT NOT NULL, "
			"chainDirection TEXT, "
			"permissionStatus TEXT, "
			"protocol TEXT, "
			"srcIp TEXT, "
			"srcPort TEXT, "
			"dstIp TEXT, "
			"dstPort TEXT, "
			"state TEXT, "
			"ruleOrigin INTEGER, "
			"prio INTEGER, "
			"PRIMARY KEY (policyId ASC)"
			");";

		// 执行SQL语句
		rc = sqlite3_exec(g_sqlite3_db, create_table_sql, 0, 0, &err_msg);

		if (rc != SQLITE_OK) {
			fprintf(stderr, "创建表失败: %s\n", err_msg);
			sqlite3_free(err_msg);
			return -1;
		}
	}

	return 0;
}

void manage_control()
{
	// 外部事务：预留外部组件调用接口，暂时没有功能实现
	external_proc();

	// 内部事务：内部功能回调，默认mqtt端
	internal_proc();

	// 管理模块：包含异常捕捉、以及协议端对象初始化
	ctrl_proc();

	// redis/db初始化
	sqlite3_init();

	// http初始化
	http_init();

	map_init(&g_SubDeviceID);
	map_init(&g_CcoStaDeviceID);
	pthread_mutex_init(&g_clientMutex, NULL);
}

void manage_free()
{
	// http释放
	http_free();

	// sqlite3释放
	sqlite3_close(g_sqlite3_db);

}

void dispach_proc()
{
	// mqtt客户端
	if (MQTT_PROTOCOL && (g_mqtt_ob.status == 1))
	{
		g_mqtt_ob.setLoginConfig();
		dzlog_info("g_mqtt_ob setLoginConfig...");
		// g_mqtt_ob.setCallbacks();
		g_mqtt_ob.Login();
		dzlog_info("g_mqtt_ob Login...");
		g_mqtt_ob.pthread_manage();
		dzlog_info("g_mqtt_ob pthread_manage...");
		g_mqtt_ob.setCallbacks(g_st_model_ctl);
		dzlog_info("g_mqtt_ob setCallbacks...");
	}

	// SOCKET TCP 服务
	/*
	if(TCP_PROTOCOL)
	{

	}*/

	// GB客户端
	if (GB_TARGET && (g_gb_ob.status == 1))
	{
	}
}

void setExternalCallbacks()
{
	IOTA_SetExternalCallback(EN_IOTA_CALLBACK_EXTERNAL_INTERFACE1, handleExternalInterface1);
}

void setInternalCallbacks()
{
	IOTA_SetCallback(EN_IOTA_CALLBACK_CONNECT_SUCCESS, handleLoginSuccess);
	IOTA_SetCallback(EN_IOTA_CALLBACK_DISCONNECT_SUCCESS, handleLogoutSuccess);
	IOTA_SetCallback(EN_IOTA_CALLBACK_SUBSCRIBE_SUCCESS, handleSubscribeSuccess);
	IOTA_SetCallback(EN_IOTA_CALLBACK_PUBLISH_SUCCESS, handlePublishSuccess);
	IOTA_SetCallback(EN_IOTA_CALLBACK_COMMAND_ARRIVED, handleCommandArrived);
}

void setExceptCallbacks()
{
	IOTA_SetCallback(EN_IOTA_CALLBACK_CONNECT_FAILURE, handleLoginFailure);
	IOTA_SetCallback(EN_IOTA_CALLBACK_CONNECTION_LOST, handleConnectionLost);
	IOTA_SetCallback(EN_IOTA_CALLBACK_DISCONNECT_FAILURE, handleLogoutFailure);
	IOTA_SetCallback(EN_IOTA_CALLBACK_SUBSCRIBE_FAILURE, handleSubscribeFailure);
	IOTA_SetCallback(EN_IOTA_CALLBACK_PUBLISH_FAILURE, handlePublishFailure);
}

int config_init(dictionary **ini, dictionary **iniMqtt, dictionary **iniRule)
{
	*ini = iniparser_load(SmartProbe_ini);
	if (*ini == NULL)
		return -1;

	pid_t pid = getpid();
	// mqtt 版本号
	VERSION_NO = iniparser_getstring(*ini, "version:version_no", "NULL");
	dzlog_warn("#################EagleEyeSMG version no:%s#################", VERSION_NO);
	dzlog_warn("#################EagleEyeSMG build time:%s %s#################", __DATE__, __TIME__);
	dzlog_warn("#################EagleEyeSMG has started running. Self PID[%d]#################", pid);

	// 认证文件
	AUTH_PATH = iniparser_getstring(*ini, "auth:auth_path", "NULL");
	dzlog_info("EagleEyeSMG AUTH_PATH:%s", AUTH_PATH);

	// mqtt 协议支持
	MQTT_PROTOCOL = iniparser_getint(*ini, "protocol:mqtt", 1);

	// sqlite db路径
	DB_FILENAME = iniparser_getstring(*ini, "db:filename", "mqtt.db");
	// docker访问路径
	DOCKER_URL = iniparser_getstring(*ini, "docker:dockerurl", "http://localhost:2375");
	DOCKER_SOCK = iniparser_getstring(*ini, "docker:dockersock", "/var/run/docker.sock");
	DOCKER_PATH = iniparser_getstring(*ini, "docker:dockerpath", "./docker");

	// 模块控制
	g_st_model_ctl.appFlag = iniparser_getint(*ini, "model:app", 1);
	g_st_model_ctl.deviceFlag = iniparser_getint(*ini, "model:device", 1);
	g_st_model_ctl.securityFlag = iniparser_getint(*ini, "model:security", 1);
	g_st_model_ctl.virtualizationFlag = iniparser_getint(*ini, "model:virtualization", 1);
	g_st_model_ctl.diagnosticsFlag = iniparser_getint(*ini, "model:diagnostics", 1);
	g_st_model_ctl.safeFlag = iniparser_getint(*ini, "model:safe", 1);
	g_st_model_ctl.web = iniparser_getint(*ini, "model:web", 0);   //默认不开了，都走离线； 需求变再说
	g_st_model_ctl.third = iniparser_getint(*ini, "model:third", 1);
	g_st_model_ctl.plc = iniparser_getint(*ini, "model:plc", 1);

	dzlog_info("------------------------>[%d]]\n", g_st_model_ctl.web);
	// 功能使能开关
	g_st_model_ctl._4gModules = 1; // 默认启用，如果等self_checking_thread检查设置成1，会慢，有概率慢过baseInfo中获取4G模块，导致跳过4G模块获取

	// mqtt客户端配置
	*iniMqtt = iniparser_load(mqtt_ini);
	if (*iniMqtt == NULL)
		return -1;
	// 文件服务地址
	FILE_SERVER_IP = iniparser_getstring(*iniMqtt, "file_server:server_addr", "NULL");
	FILE_SERVER_PORT = iniparser_getint(*iniMqtt, "file_server:port", 0);
	LOGIN_PORT = iniparser_getint(*iniMqtt, "file_server:port", 0);
	ACTIVATION_PORT = iniparser_getint(*iniMqtt, "file_server:activation_port", 0);

	LOGIN_ADDR = iniparser_getstring(*iniMqtt, "file_server:server_addr", "NULL");
	LOGIN_USER = "";
	LOGIN_PASSWORD = "";
	LOGIN_ZONE = "";
	LOGIN_NODE = "";
	FILE_LOG = iniparser_getstring(*iniMqtt, "file_server:file_log", "NULL");
	UPDATE_FILE_PATH = iniparser_getstring(*iniMqtt, "file_server:update_file_path", "NULL");
	APP_FILE_PATH = iniparser_getstring(*iniMqtt, "file_server:app_file_path", "NULL");
	PRIORITY_CONF = iniparser_getint(*iniMqtt, "file_server:priorityconf", 0);
	HTTP_SSL = iniparser_getint(*iniMqtt, "file_server:SSL", 0);
	Activation_SSL = iniparser_getint(*iniMqtt, "file_server:activation_ssl", 2);
	CLIENT_SIGN_CERT_PATH = iniparser_getstring(*iniMqtt, "file_server:client_sign_cert", "./client_sign.crt");
	CLIENT_SIGN_KEY_PATH = iniparser_getstring(*iniMqtt, "file_server:client_sign_key", "./client_sign.key");
	CLIENT_ENC_CERT_PATH = iniparser_getstring(*iniMqtt, "file_server:client_enc_cert", "./client.crt");
	CLIENT_ENC_KEY_PATH = iniparser_getstring(*iniMqtt, "file_server:client_enc_key", "./client.key");
	CLIENT_CA_CERT_PATH = iniparser_getstring(*iniMqtt, "file_server:capath", "./ca.crt");

	CLIENT_CA_CERT_PATH_V1 = iniparser_getstring(*iniMqtt, "file_server:capath_1", "./conf/certs/ca.pem");
	CLIENT_SIGN_CERT_PATH_V1 = iniparser_getstring(*iniMqtt, "file_server:client_sign_cert_1", "./conf/certs/client.pem");
	CLIENT_SIGN_KEY_PATH_V1 = iniparser_getstring(*iniMqtt, "file_server:client_sign_key_1", "./conf/certs/client.key");

	IS_HTTPS = iniparser_getint(*iniMqtt, "file_server:https", 0);
	file_sencrypt = iniparser_getint(*iniMqtt, "file_server:sencrypt", 1);
	SD_ADDR_PORT = iniparser_getstring(*iniMqtt, "sd_server:port", "9005");
	SD_TEM_CERT_ADDR_PORT = iniparser_getstring(*iniMqtt, "sd_server:tmp_cert_port", "9002");
	SD_CERT_ADDR_PORT = iniparser_getstring(*iniMqtt, "sd_server:cert_port", "8003");
	SD_FRONT_PORT = iniparser_getstring(*iniMqtt, "sd_server:front_port", "9001");
 
	WEB_ADDR_PATH = iniparser_getstring(*iniMqtt, "web_server:ip", "localhost");
	WEB_ADDR_PORT = iniparser_getstring(*iniMqtt, "web_server:port", "7080");

	readMQTTClientCfg(*iniMqtt, &g_mqtt_ob.clientInfo);

	try_get_autoconf_v3();

	// 告警规则配置
	*iniRule = iniparser_load(rule_ini);
	if (*iniRule == NULL)
		return -1;
	readAlarmRule(*iniRule);

	dzlog_info("#################EagleEyeSMG end#################");
	return 0;
}

int try_get_autoconf_v3()
{
	const char* cmd = "devinfo -a";
	char* json_string = NULL;
	dzlog_info("try_get_autoconf 11 cmd[%s]", cmd);
	int ret = popen_get_json(&json_string, cmd);
	dzlog_info("try_get_autoconf 22 ret[%d] json_string[%s]", ret, json_string);
	if (ret == 0)
	{
		// 解析 JSON 字符串
		cJSON* json_result = NULL;
		json_result = cJSON_Parse(json_string);
		if (!json_result)
		{
			dzlog_info("Error: \"ESN\" is not a valid JSON\n");
			free(json_string);
			return -1;
		}
		cJSON* item = NULL;
		item = cJSON_GetObjectItem(json_result, "ESN");
		if (item && cJSON_IsString(item))
		{
			char* result = malloc(64);
			memset(result, 0, 64);
			strncpy(result, item->valuestring, 31);
			result[32] = '\0';
			g_mqtt_ob.clientInfo.device_id = result;
			g_mqtt_ob.clientInfo.client_id = result;
			dzlog_info("ESN result[%s]", result);
		}
		item = cJSON_GetObjectItem(json_result, "device_type");
		if (item && cJSON_IsString(item))
		{
			char* result = malloc(128);
			memset(result, 0, 128);
			strcpy(result, item->valuestring);
			g_mqtt_ob.clientInfo.device_type = result;
		}
		cJSON_Delete(json_result);
	}
	else
	{
		// 错误处理
		dzlog_info("Error: \"popen_get_json:%s\"", cmd);
	}
	free(json_string);

	return 0;
}

char *get_nodeId()
{
	const char* cmd = "devinfo -a";
	char* json_string = NULL;
	dzlog_info("get_nodeId cmd[%s]", cmd);
	int ret = popen_get_json(&json_string, cmd);
	dzlog_info("get_nodeId ret[%d] json_string[%s]", ret, json_string);
	if (ret == 0)
	{
		// 解析 JSON 字符串
		cJSON* json_result = NULL;
		json_result = cJSON_Parse(json_string);
		if (!json_result)
		{
			dzlog_info("Error: \"ESN\" is not a valid JSON\n");
			free(json_string);
			return NULL;
		}
		cJSON* item = NULL;
		item = cJSON_GetObjectItem(json_result, "ESN");
		if (item && cJSON_IsString(item))
		{
			char* result = malloc(64);
			memset(result, 0, 64);
			strncpy(result, item->valuestring, 63);
			result[63] = '\0';
			dzlog_info("ESN result[%s]", result);
			free(json_string);
			cJSON_Delete(json_result);
			return result;
		}
	}
	else
	{
		// 错误处理
		dzlog_info("Error: \"popen_get_json:%s\"", cmd);
	}
	free(json_string);

	return NULL;
}
